﻿using System;
using System.Data.Objects;
using System.IO;
using EFTracingProvider;
using EFProviderWrapperToolkit;

namespace UtfprLibrary.EntityFramework {
    /// <summary>
    /// Add tracing capabilities to an ObjectContext
    /// <para> example: </para>
    /// <para> ... </para>
    /// <para> using EFTracingProvider; </para>
    /// <para> public class EdmContext : EdmEntities, <see cref="IObjectContextTracingProvider"/> { </para>
    /// <para> public EdmContext(string connectionString) </para>
    /// <para> : base(EFTracingProviderUtils.CreateTracedEntityConnection(connectionString)) { </para>
    /// <para> this.EnableTracing(); </para>
    /// <para> } </para>
    /// <para> public <see cref="ObjectContextTracing"/> Tracing { </para>
    /// <para> get { return new ObjectContextTracing(this); } </para>
    /// <para> } </para>
    /// <para> } </para>
    /// </summary>
    public partial class ObjectContextTracing {
        public ObjectContextTracing(ObjectContext context) {
            this._context = context;
        }

        #region Tracing Extensions

        #region Events

        public event EventHandler<CommandExecutionEventArgs> CommandExecuting {
            add { this.tracingConnection.CommandExecuting += value; }
            remove { this.tracingConnection.CommandExecuting -= value; }
        }

        public event EventHandler<CommandExecutionEventArgs> CommandFinished {
            add { this.tracingConnection.CommandFinished += value; }
            remove { this.tracingConnection.CommandFinished -= value; }
        }

        public event EventHandler<CommandExecutionEventArgs> CommandFailed {
            add { this.tracingConnection.CommandFailed += value; }
            remove { this.tracingConnection.CommandFailed -= value; }
        }

        #endregion

        #region Properties

        private EFTracingConnection tracingConnection {
            get { return _context.UnwrapConnection<EFTracingConnection>(); }
        }

        private ObjectContext _context;
        public  ObjectContext ObjectContext {
            get { return _context; }
        }

        private TextWriter logOutput;
        public TextWriter Log {
            get { return this.logOutput; }
            set {
                if ((this.logOutput != null) != (value != null)) {
                    if (value == null) {
                        CommandExecuting -= AppendToLog;
                    } else {
                        CommandExecuting += AppendToLog;
                    }
                }

                this.logOutput = value;
            }
        }

        #endregion

        #region Methods

        private void AppendToLog(object sender, CommandExecutionEventArgs e) {
            if (this.logOutput != null) {
                this.logOutput.WriteLine(e.ToTraceString().TrimEnd());
                this.logOutput.WriteLine();
            }
        }

        #endregion

        #endregion
    }
}
